#include "Control/GUIWindow.h"
#include "GUISystem.h"
#include "GUIBase.h"
#include "GUILogger.h"

const YGUI::String YGUI::Window::EventClippedByParentChanged("ClippedByParentChanged");
const YGUI::String YGUI::Window::EventRenderBegin("RenderBegin");
const YGUI::String YGUI::Window::EventRenderEnd("RenderEnd");
const YGUI::String YGUI::Window::EventTextChagned("TextChanged");
const YGUI::String YGUI::Window::EventAlphaChanged("AlphaChanged");
const YGUI::String YGUI::Window::EventShown("Shown");
const YGUI::String YGUI::Window::EventHidden("Hidden");
const YGUI::String YGUI::Window::EventDislabed("Disabled");
const YGUI::String YGUI::Window::EventEnabled("Enabled");
const YGUI::String YGUI::Window::EventPositionChanged("PositionChanged");
const YGUI::String YGUI::Window::EventSizeChanged("SizeChanged");
const YGUI::String YGUI::Window::EventZOrderChanged("ZOrderChanged");
const YGUI::String YGUI::Window::EventDestroyBeginning("DestroyBeginning");
const YGUI::String YGUI::Window::EventActived("Actived");
const YGUI::String YGUI::Window::EventDeactivated("Deactivated");
const YGUI::String YGUI::Window::EventCaptureGained("CaptureGained");
const YGUI::String YGUI::Window::EventCaptureLost("CaptureLost");
const YGUI::String YGUI::Window::EventMouseMove("MouseMove");
const YGUI::String YGUI::Window::EventMouseEnter("MouseEnter");
const YGUI::String YGUI::Window::EventMouseLeave("MouseLeave");
const YGUI::String YGUI::Window::EventMouseButtonDown("MouseButtonDown");
const YGUI::String YGUI::Window::EventMouseButtonUp("MouseButtonUp");
const YGUI::String YGUI::Window::EventMouseClick("MouseClick");
const YGUI::String YGUI::Window::EventMouseDoubleClick("MouseDoubleClick");


const YGUI::String YGUI::Window::WidgetTypeName("Window");
const YGUI::String YGUI::Window::TypeName("Window");

const YGUI::String YGUI::Window::AutoWidgetNameSuffix("__auto_");

namespace YGUI
{
    void Window::onClippingChanged(WindowEventArgs& e)
    {
        this->invalidate();
        this->notifyClippingChanged();
        EventSet::fireEvent(EventClippedByParentChanged, e);
    }

    void Window::onRenderBegin(WindowEventArgs& e)
    {
        EventSet::fireEvent(EventRenderBegin, e);
    }

    void Window::onRenderEnd(WindowEventArgs& e)
    {
        EventSet::fireEvent(EventRenderEnd, e);
    }

    void Window::onTextChanged(WindowEventArgs& e)
    {
        EventSet::fireEvent(EventTextChagned, e);
    }

    void Window::onAlphaChanged(WindowEventArgs& e)
    {
        EventSet::fireEvent(EventAlphaChanged, e);
    }

    void Window::onShown(YGUI::WindowEventArgs& e)
    {
        EventSet::fireEvent(EventShown, e);
    }

    void Window::onHidden(YGUI::WindowEventArgs& e)
    {
        EventSet::fireEvent(EventHidden, e);
    }

    void Window::onDisabled(WindowEventArgs& e)
    {
        EventSet::fireEvent(EventDislabed, e);
    }

    void Window::onEnabled(WindowEventArgs& e)
    {
        EventSet::fireEvent(EventEnabled, e);
    }

    void Window::onPositionChanged(WindowEventArgs& e)
    {
        notifyScreenAreaChanged();
        if(m_parent)
        {
            m_parent->invalidateRenderingSurface();
            RenderingSurface* rs = m_parent->getRenderingSurface();
            if(rs && rs->isRenderingWindow())
                System::getSingleton().invalidate();
        }
        EventSet::fireEvent(EventPositionChanged, e);
    }

    void Window::onSizeChanged(WindowEventArgs& e)
    {
        this->notifyAreaChanged();
        EventSet::fireEvent(EventSizeChanged, e);
    }

    void Window::onZOrderChanged(WindowEventArgs& e)
    {
        EventSet::fireEvent(EventZOrderChanged, e);
    }

    void Window::onDestroyBeginning(WindowEventArgs& e)
    {
        EventSet::fireEvent(EventDestroyBeginning, e);
    }

    void Window::onActived(WindowActivationEventArgs& e)
    {
        m_active = true;
        this->invalidate();
        EventSet::fireEvent(EventActived, e);
    }

    void Window::onDeactived(WindowActivationEventArgs& e)
    {
        EventSet::fireEvent(EventDeactivated, e);
    }

    void Window::onCaptureGained(WindowEventArgs& e)
    {
        EventSet::fireEvent(EventCaptureGained, e);
    }

    void Window::onCaptureLost(WindowEventArgs& e)
    {
        EventSet::fireEvent(EventCaptureLost, e);
    }

    void Window::onMouseMove(MouseEventArgs& e)
    {
        if(m_draging)
        {
            Vector2<float> delta(CoordConverter::screenToClient(this, e.Position));
            delta -= m_dragPoint;
            mouseMoveWindow_impl(delta);
        }
        EventSet::fireEvent(EventMouseMove, e);
    }

    void Window::onMouseEnter(MouseEventArgs& e)
    {
        Logger::getSingleton().wprintf(L"%s MouseButton Enter\n", m_name.w_str());
        EventSet::fireEvent(EventMouseEnter, e);
    }

    void Window::onMouseLeave(MouseEventArgs& e)
    {
        Logger::getSingleton().wprintf(L"%s MouseButton Leave\n", m_name.w_str());
        EventSet::fireEvent(EventMouseLeave, e);
    }

    void Window::onMouseButtonDown(MouseEventArgs& e)
    {
        Logger::getSingleton().wprintf(L"%s MouseButton Down\n", m_name.w_str());
        if(e.Button == MB_Left && moveToFront_impl(true))
            ++e.m_handled;
        EventSet::fireEvent(EventMouseButtonDown, e);
        ++e.m_handled;
        if(this->isActive() && System::getSingleton().getCaptureWindow() == this && m_dragEnabled)
        {
            m_draging = true;
            m_dragPoint = CoordConverter::screenToClient(this, e.Position);
            ++e.m_handled;
        }
    }

    void Window::onMouseButtonUp(MouseEventArgs& e)
    {
        Logger::getSingleton().wprintf(L"%s MouseButton Up\n", m_name.w_str());
        EventSet::fireEvent(EventMouseButtonUp, e);
        if(m_draging && System::getSingleton().getCaptureWindow() == this)
        {
            m_draging = false;
            ++e.m_handled;
        }
        ++e.m_handled;
    }

    void Window::onMouseButtonClick(MouseEventArgs& e)
    {
        EventSet::fireEvent(EventMouseClick, e);
    }

    void Window::onMouseDoubleClick(MouseEventArgs& e)
    {
        EventSet::fireEvent(EventMouseDoubleClick, e);
    }
};